library ieee;
use ieee.std_logic_1164.all;

-- This arbitrary state machine is probably not very useful in reality, but demonstrates 

entity forward_test is
    port (clock               : in  std_logic;
          reset               : in  std_logic;
          FWD_to_RCV0_LENGTH_ACK, FWD_to_RCV1_LENGTH_ACK, FWD_to_RCV2_LENGTH_ACK, FWD_to_RCV3_LENGTH_ACK 	: OUT STD_LOGIC;
	      FWD_to_RCV0_FRAME_ACK, FWD_to_RCV1_FRAME_ACK, FWD_to_RCV2_FRAME_ACK, FWD_to_RCV3_FRAME_ACK		: OUT STD_LOGIC;
	      FWD_to_TBL_ACK																					: OUT STD_LOGIC;
		  FWD_to_TBL_desAddress																				: OUT STD_LOGIC_VECTOR(47 DOWNTO 0);
	      FWD_to_TBL_srcPort																				: OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
	      FWD_to_TBL_srcAddress																				: OUT STD_LOGIC_VECTOR(47 DOWNTO 0);
	      FWD_to_XMT0_DATA, FWD_to_XMT1_DATA, FWD_to_XMT2_DATA, FWD_to_XMT3_DATA							: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	      FWD_to_XMT0_ACK, FWD_to_XMT1_ACK, FWD_to_XMT2_ACK, FWD_to_XMT3_ACK								: OUT STD_LOGIC;
	      FWD_to_XMT0_DONE, FWD_to_XMT1_DONE, FWD_to_XMT2_DONE, FWD_to_XMT3_DONE							: OUT STD_LOGIC;
	      FWD_to_XMT0_LENGTH, FWD_to_XMT1_LENGTH, FWD_to_XMT2_LENGTH, FWD_to_XMT3_LENGTH					: OUT STD_LOGIC_VECTOR(10 DOWNTO 0)
	      );
end forward_test;

architecture behavior of forward_test is

signal RCV0_to_FWD_DATA, RCV1_to_FWD_DATA, RCV2_to_FWD_DATA, RCV3_to_FWD_DATA											: STD_LOGIC_VECTOR(7 DOWNTO 0);
signal RCV0_to_FWD_LENGTH, RCV1_to_FWD_LENGTH, RCV2_to_FWD_LENGTH, RCV3_to_FWD_LENGTH									: STD_LOGIC_VECTOR(11 DOWNTO 0);
signal RCV0_to_FWD_FRAMEAVAILABLE, RCV1_to_FWD_FRAMEAVAILABLE, RCV2_to_FWD_FRAMEAVAILABLE, RCV3_to_FWD_FRAMEAVAILABLE	: STD_LOGIC;
signal TBL_to_FWD_ACK, TBL_to_FWD_Valid																					: STD_LOGIC;
signal TBL_to_FWD_Port																									: STD_LOGIC_VECTOR(2 DOWNTO 0);
	   
signal XMT0_to_FWD_spaceavailable, XMT1_to_FWD_spaceavailable, XMT2_to_FWD_spaceavailable, XMT3_to_FWD_spaceavailable	: STD_LOGIC_VECTOR(10 DOWNTO 0);
signal XMT0_to_FWD_ACK, XMT1_to_FWD_ACK, XMT2_to_FWD_ACK, XMT3_to_FWD_ACK												: STD_LOGIC;
    
signal en_0,en_1,en_2			                                                                                        : std_logic := '0';
signal q																												: std_logic_vector(254 downto 0);
signal gen_0,gen_1,gen_2 : std_logic_vector(255 downto 0) := (255 downto 0 =>'0'); --"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
       
       
component Test_Forwarding_Engine is
   
    port(
	   clk, reset								: IN STD_LOGIC;
	   -- Interface with receive team
	   RCV0_to_FWD_DATA							: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
	   RCV0_to_FWD_LENGTH						: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
	   RCV0_to_FWD_FRAMEAVAILABLE				: IN STD_LOGIC;
	   FWD_to_RCV0_LENGTH_ACK					: OUT STD_LOGIC;
	   FWD_to_RCV0_FRAME_ACK					: OUT STD_LOGIC;
	   
	   RCV1_to_FWD_DATA							: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
	   RCV1_to_FWD_LENGTH						: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
	   RCV1_to_FWD_FRAMEAVAILABLE				: IN STD_LOGIC;
	   FWD_to_RCV1_LENGTH_ACK					: OUT STD_LOGIC;
	   FWD_to_RCV1_FRAME_ACK					: OUT STD_LOGIC;
	   
	   RCV2_to_FWD_DATA							: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
	   RCV2_to_FWD_LENGTH						: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
	   RCV2_to_FWD_FRAMEAVAILABLE				: IN STD_LOGIC;
	   FWD_to_RCV2_LENGTH_ACK					: OUT STD_LOGIC;
	   FWD_to_RCV2_FRAME_ACK					: OUT STD_LOGIC;
	   
	   RCV3_to_FWD_DATA							: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
	   RCV3_to_FWD_LENGTH						: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
	   RCV3_to_FWD_FRAMEAVAILABLE				: IN STD_LOGIC;
	   FWD_to_RCV3_LENGTH_ACK					: OUT STD_LOGIC;
	   FWD_to_RCV3_FRAME_ACK					: OUT STD_LOGIC;
	   
	   -- Interface with table team
	   TBL_to_FWD_ACK							: IN STD_LOGIC;
	   TBL_to_FWD_Valid							: IN STD_LOGIC;
	   TBL_to_FWD_Port							: IN STD_LOGIC_VECTOR(2 DOWNTO 0);
	   FWD_to_TBL_ACK							: OUT STD_LOGIC;
	   FWD_to_TBL_desAddress					: OUT STD_LOGIC_VECTOR(47 DOWNTO 0);
	   FWD_to_TBL_srcPort						: OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
	   FWD_to_TBL_srcAddress					: OUT STD_LOGIC_VECTOR(47 DOWNTO 0);
	   
	   -- Interface with xmt team
	   XMT0_to_FWD_spaceavailable				: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
	   XMT0_to_FWD_ACK							: IN STD_LOGIC;
	   FWD_to_XMT0_DATA							: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	   FWD_to_XMT0_ACK							: OUT STD_LOGIC;
	   FWD_to_XMT0_DONE							: OUT STD_LOGIC;
	   FWD_to_XMT0_LENGTH						: OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
	   
	   XMT1_to_FWD_spaceavailable				: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
	   XMT1_to_FWD_ACK							: IN STD_LOGIC;
	   FWD_to_XMT1_DATA							: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	   FWD_to_XMT1_ACK							: OUT STD_LOGIC;
	   FWD_to_XMT1_DONE							: OUT STD_LOGIC;
	   FWD_to_XMT1_LENGTH						: OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
    
	   XMT2_to_FWD_spaceavailable				: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
	   XMT2_to_FWD_ACK							: IN STD_LOGIC;
	   FWD_to_XMT2_DATA							: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	   FWD_to_XMT2_ACK							: OUT STD_LOGIC;
	   FWD_to_XMT2_DONE							: OUT STD_LOGIC;
	   FWD_to_XMT2_LENGTH						: OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
    
       XMT3_to_FWD_spaceavailable				: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
	   XMT3_to_FWD_ACK							: IN STD_LOGIC;
	   FWD_to_XMT3_DATA							: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	   FWD_to_XMT3_ACK							: OUT STD_LOGIC;
	   FWD_to_XMT3_DONE							: OUT STD_LOGIC;
	   FWD_to_XMT3_LENGTH						: OUT STD_LOGIC_VECTOR(10 DOWNTO 0)
    
       );
       
end component;

component test_bench_256 is
    port (clock               : in  std_logic;
          reset               : in  std_logic;
          q                   : out std_logic_vector(254 downto 0);
          en_0, en_1, en_2    : out std_logic;
          gen_0, gen_1, gen_2 : in  std_logic_vector(255 downto 0)
    );
end component;

begin

bench: test_bench_256 port map(clock,reset,q,en_0,en_1,en_2,gen_0,gen_1,gen_2);
fwd: Test_Forwarding_Engine port map(clock,reset,RCV0_to_FWD_DATA, RCV0_to_FWD_LENGTH, RCV0_to_FWD_FRAMEAVAILABLE, FWD_to_RCV0_LENGTH_ACK,
	   FWD_to_RCV0_FRAME_ACK, RCV1_to_FWD_DATA, RCV1_to_FWD_LENGTH, RCV1_to_FWD_FRAMEAVAILABLE, FWD_to_RCV1_LENGTH_ACK, FWD_to_RCV1_FRAME_ACK,
	   RCV2_to_FWD_DATA, RCV2_to_FWD_LENGTH, RCV2_to_FWD_FRAMEAVAILABLE, FWD_to_RCV2_LENGTH_ACK, FWD_to_RCV2_FRAME_ACK, RCV3_to_FWD_DATA,	
	   RCV3_to_FWD_LENGTH, RCV3_to_FWD_FRAMEAVAILABLE, FWD_to_RCV3_LENGTH_ACK, FWD_to_RCV3_FRAME_ACK, TBL_to_FWD_ACK, TBL_to_FWD_Valid,		
	   TBL_to_FWD_Port, FWD_to_TBL_ACK, FWD_to_TBL_desAddress, FWD_to_TBL_srcPort, FWD_to_TBL_srcAddress, XMT0_to_FWD_spaceavailable,
	   XMT0_to_FWD_ACK, FWD_to_XMT0_DATA, FWD_to_XMT0_ACK, FWD_to_XMT0_DONE, FWD_to_XMT0_LENGTH, XMT1_to_FWD_spaceavailable, XMT1_to_FWD_ACK,
	   FWD_to_XMT1_DATA, FWD_to_XMT1_ACK, FWD_to_XMT1_DONE, FWD_to_XMT1_LENGTH, XMT2_to_FWD_spaceavailable, XMT2_to_FWD_ACK, FWD_to_XMT2_DATA,
	   FWD_to_XMT2_ACK, FWD_to_XMT2_DONE, FWD_to_XMT2_LENGTH, XMT3_to_FWD_spaceavailable, XMT3_to_FWD_ACK, FWD_to_XMT3_DATA, FWD_to_XMT3_ACK,
	   FWD_to_XMT3_DONE,FWD_to_XMT3_LENGTH);
       
RCV0_to_FWD_DATA <= q(7 downto 0);
RCV0_to_FWD_LENGTH <= q(19 downto 8);
RCV0_to_FWD_FRAMEAVAILABLE <= q(20);
	   
RCV1_to_FWD_DATA <= q(28 downto 21);
RCV1_to_FWD_LENGTH <= q(40 downto 29);
RCV1_to_FWD_FRAMEAVAILABLE <= q(41);

RCV2_to_FWD_DATA <= q(49 downto 42);
RCV2_to_FWD_LENGTH <= q(61 downto 50);
RCV2_to_FWD_FRAMEAVAILABLE <= q(62);

RCV3_to_FWD_DATA <= q(70 downto 63);
RCV3_to_FWD_LENGTH <= q(82 downto 71);
RCV3_to_FWD_FRAMEAVAILABLE <= q(83);
	   
TBL_to_FWD_ACK <= q(84);
TBL_to_FWD_Valid <= q(85);
TBL_to_FWD_Port	<= q(88 downto 86);

XMT0_to_FWD_spaceavailable <= q(99 downto 89);
XMT0_to_FWD_ACK	<= q(100);
	   
XMT1_to_FWD_spaceavailable <= q(111 downto 101);
XMT1_to_FWD_ACK	<= q(112);

XMT2_to_FWD_spaceavailable <= q(123 downto 113);
XMT2_to_FWD_ACK	<= q(124);

XMT3_to_FWD_spaceavailable <= q(135 downto 125);
XMT3_to_FWD_ACK	<= q(136);

end behavior;